package org.shock.ss.sms.commons.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.shock.ss.sms.commons.db.TsDbTools;
import org.shock.ss.sms.bean.Pager;
import org.shock.ss.sms.commons.db.ProxoolDbPool;
import org.shock.ss.sms.commons.dao.BaseDao;
import com.sun.org.apache.commons.beanutils.BeanUtils;

/**
 * BaseDao 的实现类 实现增删改查
 * 
 * @author jile
 * 
 */
public class BaseDaoImpl<T> implements BaseDao<T> {
	protected Connection conn;
	protected String sql;
	protected Logger log = Logger.getLogger(getClass());

	@SuppressWarnings("unchecked")
	public void add(T bean) throws Exception {
		PreparedStatement ps;
		@SuppressWarnings("unused")
		Field field = bean.getClass().getDeclaredField("table");
		field.setAccessible(true);
		String table = (String) field.get(bean);
		@SuppressWarnings("unused")
		StringBuffer sb1 = new StringBuffer("insert into " + table + " (");
		StringBuffer sb2 = new StringBuffer();
		List list = new ArrayList();
		Method[] m = bean.getClass().getMethods();
		/** 继承父类可以使用 modify by jile */
		for (int i = 0; i < m.length; i++) {
			if ("get".equals(m[i].getName().substring(0, 3))
					&& !"table".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& !"id".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& !"serialVersionUID".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& !"class".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& m[i].invoke(bean, new Object[] {}) != null) {
				sb1.append(m[i].getName().replace("get", "") + ",");
				sb2.append("?,");
				list.add(m[i].invoke(bean, new Object[] {}));
			}
		}
		sb1.deleteCharAt(sb1.lastIndexOf(","));
		sb1.append(") values (");
		sb2.deleteCharAt(sb2.lastIndexOf(","));
		sb2.append(")");
		sb1.append(sb2);
		sql = sb1.toString();
		log.debug(sql);
		conn = ProxoolDbPool.getConnection();
		ps = conn.prepareStatement(sql);
		for (int i = 0; i < list.size(); i++) {
			ps.setObject(i + 1, list.get(i));
		}
		ps.executeUpdate();
		ps.close();
	}

	public void del(String sql) throws Exception {
		if (!sql.contains("delete")) {
			throw new SQLException("sql语句错误，不是delete删除语句！");
		}
		PreparedStatement ps;
		log.debug(sql);
		conn = ProxoolDbPool.getConnection();
		ps = conn.prepareStatement(sql);
		ps.executeUpdate();
		ps.close();
	}

	public void del(T bean) throws Exception {
		PreparedStatement ps;
		Field tableField = bean.getClass().getDeclaredField("table");
		Field idField = bean.getClass().getDeclaredField("id");
		tableField.setAccessible(true);
		idField.setAccessible(true);
		String table = (String) tableField.get(bean);
		String id = idField.get(bean).toString();
		conn = ProxoolDbPool.getConnection();
		String sql = "delete from " + table + " where id=" + id;
		log.debug(sql);
		ps = conn.prepareStatement(sql);
		ps.executeUpdate();
		ps.close();
	}

	public Pager list(String dir, String sort, int pageno, int rownum, String sqlCount, String sql) throws Exception {
		sql += " order by " + sort + " " + dir;
		sql += " limit " + (pageno - 1) * rownum + "," + 1 * rownum;
		log.debug(sql);
		System.out.println(sql);
		System.out.println(sqlCount);
		Pager page = new Pager();
		int totalCount = TsDbTools.getInt(sqlCount);
		page.setTotalCount(totalCount);
		page.setList(TsDbTools.getMapsInList(sql));
		return page;
	}

	@SuppressWarnings("unchecked")
	public void update(Object bean) throws Exception {
		PreparedStatement ps;
		List list = new ArrayList();
		Field tableField = bean.getClass().getDeclaredField("table");
		Field idField = bean.getClass().getDeclaredField("id");
		tableField.setAccessible(true);
		idField.setAccessible(true);
		String table = (String) tableField.get(bean);
		Long id = Long.parseLong(idField.get(bean) + "");
		StringBuffer sb = new StringBuffer("update " + table + " set ");
		Method[] m = bean.getClass().getMethods();
		/** 继承父类可以使用 */
		for (int i = 0; i < m.length; i++) {
			if ("get".equals(m[i].getName().substring(0, 3))
					&& !"table".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& !"id".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& !"serialVersionUID".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& !"class".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& m[i].invoke(bean, new Object[] {}) != null) {
				sb.append(m[i].getName().replace("get", "") + "=?,");
				list.add(m[i].invoke(bean, new Object[] {}));
			}
		}
		list.add(id);
		sb.deleteCharAt(sb.lastIndexOf(","));
		sb.append(" where id=?");
		sql = sb.toString();
		log.debug(sql);
		conn = ProxoolDbPool.getConnection();
		ps = conn.prepareStatement(sql);
		for (int i = 0; i < list.size(); i++) {
			ps.setObject(i + 1, list.get(i));
		}
		log.debug(list);
		int num = ps.executeUpdate();
		log.debug("更新" + num + "条");
		ps.close();
	}

	@SuppressWarnings("unchecked")
	public Map view(String sql) throws Exception {
		log.debug(sql);
		return TsDbTools.getMap(sql);
	}

	@SuppressWarnings("unchecked")
	public List listAll(String sql) throws Exception {
		log.debug(sql);
		return TsDbTools.getMapsInList(sql);
	}

	@SuppressWarnings("unchecked")
	public T addBean(T bean) throws Exception {
		PreparedStatement ps;
		@SuppressWarnings("unused")
		Field field = bean.getClass().getDeclaredField("table");
		field.setAccessible(true);
		String table = (String) field.get(bean);
		@SuppressWarnings("unused")
		StringBuffer sb1 = new StringBuffer("insert into " + table + " (");
		StringBuffer sb2 = new StringBuffer();
		List list = new ArrayList();
		Method[] m = bean.getClass().getMethods();
		Method setid = null;
		/** 继承父类可以使用 */
		for (int i = 0; i < m.length; i++) {
			if ("id".equalsIgnoreCase(m[i].getName().replace("set", ""))) {
				setid = m[i];
			}
			if ("get".equals(m[i].getName().substring(0, 3))
					&& !"table".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& !"id".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& !"serialVersionUID".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& !"class".equalsIgnoreCase(m[i].getName().replace("get", ""))
					&& m[i].invoke(bean, new Object[] {}) != null) {
				sb1.append(m[i].getName().replace("get", "") + ",");
				sb2.append("?,");
				list.add(m[i].invoke(bean, new Object[] {}));
			}
		}
		sb1.deleteCharAt(sb1.lastIndexOf(","));
		sb1.append(") values (");
		sb2.deleteCharAt(sb2.lastIndexOf(","));
		sb2.append(")");
		sb1.append(sb2);
		sql = sb1.toString();
		log.debug(sql);
		conn = ProxoolDbPool.getConnection();
		ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
		for (int i = 0; i < list.size(); i++) {
			ps.setObject(i + 1, list.get(i));
		}
		ps.executeUpdate();
		// 将mysql自增的id赋给bean
		ResultSet rs = ps.getGeneratedKeys();
		if (rs.next()) {
			for (int i = 0; i < m.length; i++) {
				if ("id".equalsIgnoreCase(m[i].getName().replace("set", ""))) {
					setid.invoke(bean, rs.getLong(1));
				}
			}
		}
		rs.close();
		ps.close();
		return bean;
	}

	@SuppressWarnings("unchecked")
	public Integer addBatch(List<T> beanList) throws Exception {
		PreparedStatement ps = null;
		conn = ProxoolDbPool.getConnection();
		int num = 0;
		int num2 = 0;
		for (Object bean : beanList) {
			@SuppressWarnings("unused")
			Field field = bean.getClass().getDeclaredField("table");
			field.setAccessible(true);
			String table = (String) field.get(bean);
			@SuppressWarnings("unused")
			StringBuffer sb1 = new StringBuffer("insert into " + table + " (id,");
			StringBuffer sb2 = new StringBuffer();
			List list = new ArrayList();
			Method[] m = bean.getClass().getMethods();
			/** 继承父类可以使用 modify by jile */
			for (int i = 0; i < m.length; i++) {
				if ("get".equals(m[i].getName().substring(0, 3))
						&& !"table".equalsIgnoreCase(m[i].getName().replace("get", ""))
						&& !"id".equalsIgnoreCase(m[i].getName().replace("get", ""))
						&& !"serialVersionUID".equalsIgnoreCase(m[i].getName().replace("get", ""))
						&& !"class".equalsIgnoreCase(m[i].getName().replace("get", ""))
						&& m[i].invoke(bean, new Object[] {}) != null) {
					sb1.append(m[i].getName().replace("get", "") + ",");
					sb2.append("?,");
					list.add(m[i].invoke(bean, new Object[] {}));
				}
			}
			sb1.deleteCharAt(sb1.lastIndexOf(","));
			sb1.append(") values (");
			sb2.deleteCharAt(sb2.lastIndexOf(","));
			sb2.append(")");
			sb1.append(sb2);
			sql = sb1.toString();
			ps = conn.prepareStatement(sql);
			for (int i = 0; i < list.size(); i++) {
				ps.setObject(i + 1, list.get(i));
			}
			ps.addBatch();
			num++;
			num2++;
			if (num > 100) {
				num = 0;
				ps.executeBatch();
				ps.clearBatch();
			}
		}
		ps.executeBatch();
		ps.close();
		return num2;
	}

	public boolean doSql(String sql) throws Exception {
		log.debug(sql);
		return TsDbTools.doSql(sql);
	}

	@SuppressWarnings("unchecked")
	public T get(Long id) throws Exception {
		T bean = null;
		Field field = bean.getClass().getDeclaredField("table");
		field.setAccessible(true);
		sql = "select * from " + field.getName() + " where id=" + id;
		Map beanMap = view(sql);
		BeanUtils.populate(bean, beanMap);
		return bean;
	}
}
